using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using Farm.Save;

namespace Farm.Inventory
{
    public class InventoryManager : Singleton<InventoryManager>,ISaveable
    {
        [Header("物品数据")]
        public ItemDataList_SO itemDataList_SO;

        [Header("建造蓝图")] 
        public BluePrintDataList_SO BluePrintDataList;

        [Header("背包数据")] 
        public InventoryBag_SO PlayerBagTemple;
        
        public InventoryBag_SO PlayerBag;

        private InventoryBag_SO currentBoxBag;

        [Header("交易")] 
        public int playerMoney;

        public string GUID => GetComponent<DataGUID>().guid;

        private Dictionary<string, List<InventoryItem>> boxDataDict = new Dictionary<string, List<InventoryItem>>();
        public int BoxDataAmount => boxDataDict.Count;
        public ItemDetails GetItemDetails(int ID)
        {
            return itemDataList_SO.itemDetailsList.Find(i => i.itemID == ID);
        }

        private void OnEnable()
        {
            EventHandler.DropItemEvent += OnDropItemEvent;
            EventHandler.HarvestAtPlayerPosition += OnHarvestAtPlayerPosition;
            EventHandler.BuildFurnitureEvent += OnBuildFurnitureEvent;
            EventHandler.BaseBagOpenEvent += OnBaseBagOpenEvent;
            EventHandler.StartNewGameEvent += OnStartNewGameEvent;
        }

        private void OnDisable()
        {
            EventHandler.DropItemEvent-=OnDropItemEvent;
            EventHandler.HarvestAtPlayerPosition -= OnHarvestAtPlayerPosition;
            EventHandler.BuildFurnitureEvent -= OnBuildFurnitureEvent;
            EventHandler.BaseBagOpenEvent -= OnBaseBagOpenEvent;
            EventHandler.StartNewGameEvent -= OnStartNewGameEvent;
        }

        private void Start()
        {
            ISaveable saveable = this;
            saveable.RegisterSaveable();
            //EventHandler.CallUpdateInventoryUI(InventoryLocation.Player,PlayerBag.itemList);
        }

        private void OnDropItemEvent(int ID, Vector3 pos,ItemType itemType)
        {
            RemoveItem(ID,1);
        }
        
        private void OnHarvestAtPlayerPosition(int itemID)
        {
            var index = GetItemInderInBag(itemID);
            
            AddItemAtIndex(itemID,index,1);
            
            EventHandler.CallUpdateInventoryUI(InventoryLocation.Player,PlayerBag.itemList);
        }
        
        private void OnBuildFurnitureEvent(int ID, Vector3 mousePos)
        {
            RemoveItem(ID,1);
            BluePrintDetails bluePrint = BluePrintDataList.GetBluePrintDetails(ID);
            foreach (var item in bluePrint.resourceItem)
            {
                RemoveItem(item.itemID,item.itemAmount);
            }
        }
        
        private void OnBaseBagOpenEvent(SlotType slotType, InventoryBag_SO bag_SO)
        {
            currentBoxBag = bag_SO;
        }
        
        private void OnStartNewGameEvent(int index)
        {
            PlayerBag = Instantiate(PlayerBagTemple);
            playerMoney = Settings.playermoney;
            boxDataDict.Clear();
            EventHandler.CallUpdateInventoryUI(InventoryLocation.Player,PlayerBag.itemList);
        }
        

        #region 添加物品到背包
        /// <summary>
        /// 添加物品到背包
        /// </summary>
        /// <param name="item"></param>
        /// <param name="toDestroy"></param>
        public void AddItem(Item item,bool toDestroy)
        {
            //是否已经有改物品
            var index = GetItemInderInBag(item.itemID);
            
            AddItemAtIndex(item.itemID,index,1);
            if (toDestroy)
            {
                Destroy(item.gameObject);
            }
            EventHandler.CallUpdateInventoryUI(InventoryLocation.Player,PlayerBag.itemList);
        }

        private bool CheckBagCapacity()
        {
            for (int i = 0; i < PlayerBag.itemList.Count; i++)
            {
                if (PlayerBag.itemList[i].itemID==0)
                {
                    return true;
                }
            }

            return false;
        }

        private int GetItemInderInBag(int ID)
        {
            for (int i = 0; i < PlayerBag.itemList.Count; i++)
            {
                if (PlayerBag.itemList[i].itemID==ID)
                {
                    return i;
                }
            }

            return -1;
        }

        private void AddItemAtIndex(int ID, int index, int amount)
        {
            if (index==-1&&CheckBagCapacity())
            {
                var item = new InventoryItem { itemID = ID, itemAmount = amount };
                for (int i = 0; i < PlayerBag.itemList.Count;i++)
                {
                    if (PlayerBag.itemList[i].itemID==0)
                    {
                        PlayerBag.itemList[i] = item;
                        break;
                    }
                }
            }
            else
            {
                int currentAmount = PlayerBag.itemList[index].itemAmount + amount;
                var item = new InventoryItem { itemID = ID, itemAmount = currentAmount };
                PlayerBag.itemList[index] = item;
            }
        }

        #endregion


        public void SwapItem(int fromIndex, int targetIndex)
        {
            InventoryItem currentItem = PlayerBag.itemList[fromIndex];
            InventoryItem targetItem = PlayerBag.itemList[targetIndex];

            if (targetItem.itemID!=0)
            {
                PlayerBag.itemList[fromIndex] = targetItem;
                PlayerBag.itemList[targetIndex] = currentItem;
            }
            else
            {
                PlayerBag.itemList[targetIndex] = currentItem;
                PlayerBag.itemList[fromIndex] = new InventoryItem();
            }
            EventHandler.CallUpdateInventoryUI(InventoryLocation.Player,PlayerBag.itemList);
        }

        public void SwapItem(InventoryLocation locationFrom, int fromIndex, InventoryLocation locationTarget, int targetIndex)
        {
            var currentList = GetItemList(locationFrom);
            var targetList = GetItemList(locationTarget);

            InventoryItem currentItem = currentList[fromIndex];
            if (targetIndex<targetList.Count)
            {
                InventoryItem targetItem = targetList[targetIndex];

                if (targetItem.itemID!=0&&currentItem.itemID!=targetItem.itemID)//两个物体不同
                {
                    currentList[fromIndex] = targetItem;
                    targetList[targetIndex] = currentItem;
                }
                else if (currentItem.itemID == targetItem.itemID)//相同物体
                {
                    targetItem.itemAmount += currentItem.itemAmount;
                    targetList[targetIndex] = targetItem;
                    currentList[fromIndex] = new InventoryItem();
                }
                else //目标是一个空格子
                {
                    targetList[targetIndex] = currentItem;
                    currentList[fromIndex] = new InventoryItem();
                }
                EventHandler.CallUpdateInventoryUI(locationFrom,currentList);
                EventHandler.CallUpdateInventoryUI(locationTarget,targetList);
            }
        }

        private List<InventoryItem> GetItemList(InventoryLocation location)
        {
            return location switch
            {
                InventoryLocation.Player => PlayerBag.itemList,
                InventoryLocation.Box => currentBoxBag.itemList,
                _ => null
            };
        }


        private void RemoveItem(int ID, int removeAmount)
        {
            var index = GetItemInderInBag(ID);
            if (PlayerBag.itemList[index].itemAmount > removeAmount)
            {
                var amount = PlayerBag.itemList[index].itemAmount - removeAmount;
                var item = new InventoryItem
                {
                    itemID = ID,
                    itemAmount = amount
                };
                PlayerBag.itemList[index] = item;
            }
            else if (PlayerBag.itemList[index].itemAmount == removeAmount)
            {
                var item = new InventoryItem();
                PlayerBag.itemList[index] = item;
            }
            EventHandler.CallUpdateInventoryUI(InventoryLocation.Player,PlayerBag.itemList);
        }

        public void TradeItem(ItemDetails itemDetails, int amount, bool isSellTrade)
        {
            int cost = itemDetails.itemPrice * amount;
            //获取物品背包位置
            int index = GetItemInderInBag(itemDetails.itemID);

            if (isSellTrade)
            {
                if (PlayerBag.itemList[index].itemAmount>=amount)
                {
                    RemoveItem(itemDetails.itemID,amount);
                    cost = (int)(cost*itemDetails.sellPercentage);

                    playerMoney += cost;
                }
            }
            else if(playerMoney-cost>=0)
            {
                if (CheckBagCapacity())
                {
                    AddItemAtIndex(itemDetails.itemID,index,amount);
                }

                playerMoney -= cost;
            }
            
            EventHandler.CallUpdateInventoryUI(InventoryLocation.Player,PlayerBag.itemList);
        }


        public bool CheckStock(int ID)
        {
            var bluePrintDetails = BluePrintDataList.GetBluePrintDetails(ID);
            foreach (var resourceitem in bluePrintDetails.resourceItem)
            {
                var itemStock = PlayerBag.GetInventoryItem(resourceitem.itemID);
                if (itemStock.itemAmount >= resourceitem.itemAmount)
                {
                    continue;
                }
                else return false;
            }

            return true;
        }

        public List<InventoryItem> GetBoxDataList(string key)
        {
            if (boxDataDict.ContainsKey(key))
            {
                return boxDataDict[key];
            }

            return null;
        }

        public void AddBoxDataDict(Box box)
        {
            var key = box.name + box.index;
            if (!boxDataDict.ContainsKey(key))
            {
                boxDataDict.Add(key,box.boxBagData.itemList);
            }

        }

        
        public GameSaveData generateSaveData()
        {
            GameSaveData saveData = new GameSaveData();
            saveData.playerMoney = playerMoney;

            saveData.inventoryDict = new Dictionary<string, List<InventoryItem>>();
            saveData.inventoryDict.Add(PlayerBag.name,PlayerBag.itemList);

            foreach (var item in boxDataDict)
            {
                saveData.inventoryDict.Add(item.Key,item.Value);
            }

            return saveData;
        }

        public void RestoreData(GameSaveData saveData)
        {
            playerMoney = saveData.playerMoney;
            PlayerBag = Instantiate(PlayerBagTemple);
            PlayerBag.itemList = saveData.inventoryDict[PlayerBag.name];
            foreach (var item in saveData.inventoryDict)
            {
                if (boxDataDict.ContainsKey(item.Key))
                {
                    boxDataDict[item.Key] = item.Value;
                }
            }
            EventHandler.CallUpdateInventoryUI(InventoryLocation.Player,PlayerBag.itemList);
        }
    }
}

